package com.hshit.downloader.io;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

public class ShitRequest {
	public static final String TAG = ShitRequest.class.getSimpleName();
	// Default values for timeout
	public final static int CONNECTION_DEFAULT_TIMEOUT = 5000;
	public final static int SOCKET_DEFAULT_TIMEOUT = 10000;
	
	// Request method type
	// public static final int UPLOAD = 2;
	public static final int POST = 0;
	public static final int GET = 1;
	public static final int DELETE = 4;
	
	// Request information
	private String mUrl;
	private int mMethod;
	
	// User's authentication code
	private String authentication;

	// Holds the parameters list
	private Hashtable<String, String> valuesList;
	
	// Constructor
	public ShitRequest(String url, int method) {
		setUrl(url);
		setMethod(method);
		valuesList = new Hashtable<String, String>();
	}
	
	// ========================================================================
	// Method GET
	// ========================================================================
	/**
	 * Get the full <code>GET</code> request URL, in the form of:
	 * <code>URL?param1=value1&param2=value2...</code>
	 *  
	 * @return the full <code>GET</code> request URL
	 */
	public String getFullRequestURL() {
		// Making the full request url
		String url = getUrl();

		// Adding parameters
		if (valuesList.size() > 0) {
			url += "?";
			for (String name : valuesList.keySet()) {
				try {
					url += URLEncoder.encode(name, "UTF-8") + "="
							+ URLEncoder.encode(valuesList.get(name), "UTF-8") + "&";
				} catch (UnsupportedEncodingException e) {
				}
			}
			url = url.substring(0, url.length() - 1);
		}
		return url;
	}
	
	/**
	 * 
	 * @return
	 */
	public HttpGet prepareGetRequest() {
		HttpGet httpGet = new HttpGet(getFullRequestURL());
		httpGet.setParams(prepareParameters());
		prepareHeader(httpGet);
		return httpGet;
	}
	
	// ========================================================================
	// Method POST
	// ========================================================================
	/**
	 * 
	 * @return
	 */
	public HttpPost preparePostRequest() {
		HttpPost httpPost = new HttpPost(getUrl());
		httpPost.setParams(prepareParameters());
		try {
			encloseParam(httpPost);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		// Prepare the header
		prepareHeader(httpPost);
		
		return httpPost;
	}
	
	// ========================================================================
	// Method DELETE
	// ========================================================================
	/**
	 * 
	 * @return
	 */
	public HttpDelete prepareDeleteRequest() {
		HttpDelete httpDelete = new HttpDelete(getUrl());
		httpDelete.setParams(prepareParameters());
		// Prepare the header
		prepareHeader(httpDelete);
		return httpDelete;
	}
	// ========================================================================
	// Method DELETE BODY
	// ========================================================================
	/**
	 * 
	 * @return
	 */
	public HttpDeleteWithBody prepareDeleteRequestBody() {
		HttpDeleteWithBody httpDeleteBody = new HttpDeleteWithBody(getUrl());
		httpDeleteBody.setParams(prepareParameters());
		try {
			encloseParam(httpDeleteBody);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		// Prepare the header
		prepareHeader(httpDeleteBody);
		return httpDeleteBody;
	}
	// ========================================================================
	// Preparing stuffs
	// ========================================================================
	public HttpClient prepareHttpClient() {
		return new DefaultHttpClient(prepareParameters());
	}
	
	/**
	 * 
	 * @return
	 */
	private HttpParams prepareParameters() {
		HttpParams httpParam = new BasicHttpParams();
		
		// TODO: set other parameters here, like timeout or something
		HttpConnectionParams.setConnectionTimeout(
				httpParam, ShitRequest.CONNECTION_DEFAULT_TIMEOUT);
		HttpConnectionParams.setSoTimeout(
				httpParam, ShitRequest.SOCKET_DEFAULT_TIMEOUT);

		return httpParam;
	}
	/**
	 * 
	 * @param request
	 */
	private void prepareHeader(HttpRequestBase request) {
		// Set the content-type as json
		// request.setHeader("Content-type", "multipart/form-data");
		request.addHeader("Accept", "application/json");
		// if need to pass access_code
		if (getAuthentication() != null) 
			request.addHeader("Auth-Token", getAuthentication());
	}
	
	/**
	 * 
	 * @param request
	 * @throws UnsupportedEncodingException
	 */
	protected void encloseParam(HttpEntityEnclosingRequestBase request) 
			throws UnsupportedEncodingException {
		// Add your data
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        for (String key : getValuesList().keySet()) {
        	nameValuePairs.add(new BasicNameValuePair(key, getValuesList().get(key)));
		}
        request.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
	}
	
	public class HttpDeleteWithBody extends HttpEntityEnclosingRequestBase {
	    public static final String METHOD_NAME = "DELETE";
	    public String getMethod() { return METHOD_NAME; }

	    public HttpDeleteWithBody(final String uri) {
	        super();
	        setURI(URI.create(uri));
	    }
	    public HttpDeleteWithBody(final URI uri) {
	        super();
	        setURI(uri);
	    }
	    public HttpDeleteWithBody() { super(); }
	}
	
	// ========================================================================
	// Getters & setters
	// ========================================================================
	public void putIntList(String name, List<Integer> arr) {
		for (int i = 0; i < arr.size(); i++) {
			valuesList.put(name + "[" + i + "]", arr.get(i) + "");
		}
	}
	
	public void putStringList(String name, List<String> arr) {
		for (int i = 0; i < arr.size(); i++) {
			valuesList.put(name + "[" + i + "]", arr.get(i));
		}
	}
	
	public void putStringList1(String name, List<String> arr) {
		for (int i = 0; i < arr.size(); i++) {
			valuesList.put(name + "[" + i + "]", arr.get(i));
		}
	}
	public void putParam(String name, String value) {
		valuesList.put(name, value);
	}
	public String getUrl() {
		return mUrl;
	}
	public void setUrl(String mUrl) {
		this.mUrl = mUrl;
	}
	
	public int getMethod() {
		return mMethod;
	}
	public void setMethod(int mMethod) {
		this.mMethod = mMethod;
	}
	
	public Hashtable<String, String> getValuesList() {
		return valuesList;
	}
	public void setValuesList(Hashtable<String, String> valuesList) {
		this.valuesList = valuesList;
	}
	public String getAuthentication() {
		return authentication;
	}
	public void setAuthentication(String authentication) {
		this.authentication = authentication;
	}
}
